﻿using System;
using static JustMathCore.CmdRule;

namespace JMCMD
{
    /// <summary>
    /// 命令行规则，不使用Console.Input,干完就走
    /// 进度和结果通过Console.WriteLine同步
    /// 命令行可以自行保存数据文件，统一向工作目录保存，外层控制工作目录
    /// 同步规则%p info  美元符 字母 空格，由此开头的信息外层重点展示，
    /// 如果是多行信息 则跟随一个 <<=    ，比如 $p <<= ,在结束行则加上%p >>=
    /// </summary>
    class Program
    {
        static JustMathCore.CMD cmd = new JustMathCore.CMD();
        static void Main(string[] args)
        {
            Console.WriteLine("v12");
            cmd.RegHelpAction(ShowHelp);
            cmd.RegAction("importaddr", CMD_ImportAddr);
            cmd.RegAction("importaddr2db", CMD_ImportAddr2DB);
            cmd.RegAction("insertaddr", CMD_InsertAddr);
            cmd.RegAction("testaddr", CMD_TestAddr);
            cmd.RegAction("testaddr_log", CMD_TestAddr_Log);
            cmd.RegAction("genaddr", CMD_GenAddr);
            cmd.RegAction("genaddr_ml", CMD_GenAddrML);
            cmd.RegAction("checkaddr", CMD_CheckAddr);
            cmd.RegAction("checkprikey", CMD_CheckPrikey);
            cmd.Main(args);
        }
        static void ShowHelp()
        {
            //help同时也是给GUI的接口定义
            var help =
                "//导入地址功能(BTC 30分钟，onlybloomfilter)\n" +
                "importaddr(type:addrtype,srcpath:filepath,filter:filefilter,outpath:filepath)\n" +
                "\n" +
                "//导入地址功能BTC 30分钟，同時產生一個rocksdb庫(和bloomfilter)\n" +
                "importaddr2db(type:addrtype,srcpath:filepath,filter:filefilter,outpath:filepath)\n" +
                "\n" +
                "//地址查询功能()\n" +
                "testaddr(dbpath:filepath,type:addrtype,mode:[single,file,files],filepath:addr|file|path)" +
                "\n" +
                "//地址查询功能(log文件 db匹配)\n" +
                "testaddr_log(dbpath:filepath,logpath:filepath)" +
                 "\n" +
                "//地址批量产生功能，用bloomfilter初筛选\n" +
                "genaddr(dbpath:filepath,type:addrtype, ranfunc:ranfunc,ranparam:int,outpath:filepath,begin:u32,end:u32)" +
                "\n" +
                "//地址检查功能" +
                "checkaddr(type:addrtype,txt:addr)" +
                "\n" +
                "//私钥检查功能" +
                "checkprikey(type:addrtype,txt:prikey)" +
                "\n"
                ;
            cmd.Write(WriteType.Result, help);
        }
        static void CMD_ImportAddr(string[] words)
        {
            try
            {
                string type = words[1];
                string srcdir = words[2];
                string filter = words[3];
                string outpath = words[4];
                var files = System.IO.Directory.GetFiles(srcdir, filter, System.IO.SearchOption.AllDirectories);
                ImportAddr.DoImport(type, files, outpath);
            }
            catch (Exception err)
            {
                cmd.Write(WriteType.Error, err.ToString());
            }
        }
        static void CMD_ImportAddr2DB(string[] words)
        {
            try
            {
                string type = words[1];
                string srcdir = words[2];
                string filter = words[3];
                string outpath = words[4];
                var files = System.IO.Directory.GetFiles(srcdir, filter, System.IO.SearchOption.AllDirectories);
                ImportAddr.DoImport2DB(type, files, outpath);
            }
            catch (Exception err)
            {
                cmd.Write(WriteType.Error, err.ToString());
            }
        }

        static void CMD_InsertAddr(string[] words)
        {
            try
            {
                string srcpath = words[1];
                string filter = words[2];
                string dbpath = words[3];
                var files = System.IO.Directory.GetFiles(srcpath, filter, System.IO.SearchOption.AllDirectories);

                ImportAddr.DoInsertAddr2Db(dbpath, files);
            }
            catch (Exception err)
            {
                cmd.Write(WriteType.Error, err.ToString());
            }
        }
        static void CMD_CheckAddr(string[] words)
        {
            try
            {
                string type = words[1];
                string addr = words[2];
                JustMathCore.AddrTools.AddrType addrtype;
                if (!Enum.TryParse<JustMathCore.AddrTools.AddrType>(type, true, out addrtype))
                {
                    throw new Exception("error roll type");
                }
                Console.WriteLine("input addr=" + addr);
                var conv = JustMathCore.AddrTools.GetConv(addrtype);
                var hash = conv.Addr2Hash(addr);
                Console.WriteLine("hash=" + JustMathCore.HexTool.Bytes2Hexstr(hash));
                Console.WriteLine("addr=" + conv.Hash2Addr(hash));
            }
            catch (Exception err)
            {
                cmd.Write(WriteType.Error, err.ToString());
            }
        }
        static void CMD_CheckPrikey(string[] words)
        {
            try
            {
                string type = words[1];
                string prikey = words[2];
                JustMathCore.AddrTools.AddrType addrtype;
                if (!Enum.TryParse<JustMathCore.AddrTools.AddrType>(type, true, out addrtype))
                {
                    throw new Exception("error roll type");
                }
                Console.WriteLine("input prikey=" + prikey);
                var conv = JustMathCore.AddrTools.GetConv(addrtype);

                byte[] prikeybts = new byte[32];
                JustMathCore.HexTool.Hexstr2Bytes(prikey, prikeybts);
                var wif = conv.GetWif(prikeybts);
                Console.WriteLine("wif=" + wif);

                var hash = conv.GetHashAddr(prikeybts);
                Console.WriteLine("hash=" + JustMathCore.HexTool.Bytes2Hexstr(hash));
                Console.WriteLine("addr=" + conv.Hash2Addr(hash));
            }
            catch (Exception err)
            {
                cmd.Write(WriteType.Error, err.ToString());
            }
        }
        static void CMD_TestAddr(string[] words)
        {
            try
            {
                string dbpath = words[1];
                string type = words[2];
                string mode = words[3];
                string addrorpath = words[4];
                JustMathCore.AddrTools.AddrType addrtype;
                if (!Enum.TryParse<JustMathCore.AddrTools.AddrType>(type, true, out addrtype))
                {
                    throw new Exception("error roll type");
                }

                if (mode == "single")
                {
                    ImportAddr.DoTestAddr_Db(dbpath, addrtype, new string[] { addrorpath });
                }
                else if (mode == "file")
                {
                    var lines = System.IO.File.ReadAllLines(addrorpath);
                    ImportAddr.DoTestAddr_Db(dbpath, addrtype, lines);
                }
                else if (mode == "addrfiles")
                {
                    var files = System.IO.Directory.GetFiles(addrorpath, "*.addr", System.IO.SearchOption.AllDirectories);
                    ImportAddr.DoTestOldAddrFiles(dbpath, files);

                }
            }
            catch (Exception err)
            {
                cmd.Write(WriteType.Error, err.ToString());
            }
        }
        static void CMD_TestAddr_Log(string[] words)
        {
            try
            {
                string dbpath = words[1];
                string logpath = words[2];
                var files = System.IO.Directory.GetFiles(logpath, "*.txt", System.IO.SearchOption.AllDirectories);
                ImportAddr.DoTestLogFiles(dbpath, files);

            }
            catch (Exception err)
            {
                cmd.Write(WriteType.Error, err.ToString());
            }
        }
        //"genaddr(dbpath:filepath,ranfunc:ranfunc,ranparam:int,outpath:filepath,genbegin:uint32,genend:uint32)\n"+
        static void CMD_GenAddr(string[] words)
        {
            try
            {
                string dbpath = words[1];

                JustMathCore.AddrTools.AddrType addrtype;
                if (!Enum.TryParse<JustMathCore.AddrTools.AddrType>(words[2], true, out addrtype))
                {
                    throw new Exception("error roll type");
                }
                //getrantype
                Roll.RollType rantype;
                if (!Enum.TryParse<Roll.RollType>(words[3], true, out rantype))
                {
                    throw new Exception("error roll type");
                }


                byte rantoken = JustMathCore.HexTool.Hexstr2Uint8(words[4]);
                string outpath = words[5];

                var genbegin = JustMathCore.HexTool.Hexstr2Uint32(words[6]);
                var genend = JustMathCore.HexTool.Hexstr2Uint32(words[7]);


                GenAddr.DoGen(dbpath, addrtype, rantype, rantoken, outpath, genbegin, genend);

            }
            catch (Exception err)
            {
                cmd.Write(WriteType.Error, err.ToString());
            }
        }
        static void CMD_GenAddrML(string[] words)
        {
            try
            {
                string dbpath = words[1];

                JustMathCore.AddrTools.AddrType addrtype;
                if (!Enum.TryParse<JustMathCore.AddrTools.AddrType>(words[2], true, out addrtype))
                {
                    throw new Exception("error addr type");
                }

                string outpath = words[3];


                GenAddr.DoMLTest(dbpath, addrtype, outpath);

            }
            catch (Exception err)
            {
                cmd.Write(WriteType.Error, err.ToString());
            }
        }
    }

}
